/**
 * @file Aside
 * @author liaoxuezhi@baidu.com
 */
/* eslint-disable */

import * as React from 'react';
import {
  Component,
  PropTypes
} from 'react';
import * as cx from 'classnames';
import {Link} from 'react-router';
import {map as mapTree} from '../../util/tree';
import * as assign from 'object-assign';
import * as qs from 'query-string';

import './aside.scss';

export default class Aside extends Component {
  static propTypes = {
    className: PropTypes.string,
    groups: PropTypes.arrayOf(PropTypes.shape({
      label: PropTypes.string,
      children: PropTypes.arrayOf(PropTypes.shape({
        url: PropTypes.string,
        label: PropTypes.string.isRequired,
        icon: PropTypes.string,
        badge: PropTypes.any,
        children: PropTypes.array,
        active: PropTypes.bool
      }))
    })),
    folded: PropTypes.bool,
    navOpened: PropTypes.bool,
    affix: PropTypes.node,
    prefix: PropTypes.node
  };

  static defaultProps = {
    className: 'bg-dark'
  };

  constructor(props) {
    super(props);

    this.state = {
      groups: props.groups && mapTree(props.groups, item => assign({
        open: item.children && item.children.length && (item.active || item.childActive)
      }, item))
    };

    this.toggleActive = this.toggleActive.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    const props = this.props;

    if (props.groups !== nextProps.groups) {
      this.setState({
        groups: nextProps.groups && mapTree(nextProps.groups, item => assign({
          open: item.children && item.children.length && (item.active || item.childActive)
        }, item))
      });
    }
  }

  toggleActive(e, link) {
    e.preventDefault();
    e.stopPropagation();
    this.setState({
      groups: mapTree(this.state.groups, item => item === link ? assign({}, item, {
        open: !item.open
      }) : item)
    });
  }

  renderLink(link, key, props = {}, depth = 1) {
    if (link.hidden) {
      return null;
    }

    let index = link.url && link.url.indexOf('?');
    let query = null;
    let url = link.url;
    if (link.url && ~index) {
      query = qs.parse(link.url.substring(index));
      url = link.url.substring(0, index);
    }
    const folded = this.props.folded;

    const body = [
      link.children && (
        <span key="arrow" onClick={(e) => this.toggleActive(e, link)} className="pull-right text-muted">
          {link.open ? (
            <i className="fa fa-fw fa-angle-down" />
          ) : (
            <i className="fa fa-fw fa-angle-right" />
          )}
        </span>
      ),
      link.icon || folded && depth === 1 ? (<i key="icon" data-tip={link.label} className={cx("icon", link.icon || 'fa fa-info')} />) : link.isFolder ? (<i key="icon" className="fa fa-folder" />) : null,
      (<span key="label" className="text-ellipsis">{link.label}</span>)
    ];

    return (
      <li
        {...props}
        key={key}
        className={cx(props.className, {
          active: link.open
        })}
      >
        {!link.isFolder && (link.url || link.hash) ? (
          /^https?:/.test(link.url) ?  (
            <a href={link.url} target="_blank" className={cx({active: link.active})}>
              {typeof link.badge !== 'undefined' ? (
                  <b className="badge bg-info pull-right">{link.badge}</b>
                ) : null}
              {body}
            </a>
          ) : (<Link
            to={{
              pathname: url,
              hash: link.hash,
              query
            }}
            className={cx({active: link.active, 'disabled-link':link.disabled})}
          >
            {typeof link.badge !== 'undefined' ? (
                <b className="badge bg-info pull-right">{link.badge}</b>
              ) : null}
            {body}
          </Link>
        )) : (
          <a onClick={(e) => this.toggleActive(e, link)} className={cx({active: link.active})}>
            {typeof link.badge !== 'undefined' ? (
                <b className="badge bg-info pull-right">{link.badge}</b>
              ) : null}
            {body}
          </a>
        )}
        {link.children && link.children.length ? (
          <ul className="nav nav-sub dk">
            {link.children.map((link, key) => this.renderLink(link, key, {}, depth + 1))}
          </ul>
        ) : null}
      </li>
    );
  }

  renderGroups() {
    const {groups} = this.state;

    if (!groups) {
      return null;
    }

    return (
      <nav className="navi clearfix">
        <ul className="nav">
          {groups.map((group, prefix) => {
            const doms = [];

            prefix === 0 || doms.push(
              <li key={`${prefix}-divider`} className="line dk" />
            );

            doms.push(
              <li key={`${prefix}-0`} className="hidden-folded padder m-t m-b-sm text-muted text-xs">
                <span>{group.label}</span>
              </li>
            );

            group.children.forEach((link, key) => {const link = this.renderLink(link, key); link && doms.push(link)});

            return doms;
          })}
        </ul>
      </nav>
    );
  }

  render() {
    const {
      prefix,
      affix,
      className,
      navOpened
    } = this.props;

    return (
      <aside className={cx("app-aside hidden-xs", className, {"off-screen": navOpened})}>
        <div className="aside-wrap">
          <div className="navi-wrap">
            {prefix}
            {this.renderGroups()}
            {affix}
          </div>
        </div>
      </aside>
    );
  }
}
